package utstat;

/*

    q3tool -- Simple Java command line tool for querying and sending commands
              to a Quake 3 (test) server.
    Copyright (C) 1999 Philip Edelbrock
  
    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or   
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License   
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author can be contacted at: phil@netroedge.com

    Version: 1.0.0

*/

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Q3Tool  {

   static String byteToHex(byte b) {
      // Returns hex String representation of byte b
      char hexDigit[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
      };
      char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
      return new String(array);
   }

   static void dumpvals (byte arg[], int length)  {
	int i;
	for (i=4; i < length;i++) {
	   System.out.print (byteToHex(arg[i]) + " ");
	   if (((i + 1) % 16) == 0) { System.out.print ("\n"); }
	}
	System.out.print ("\n\nLength: " + length + " bytes.\n");
   }
   
   static void dumpchars (byte arg[], int length)  {
	int i;
	for (i=4; i < length;i++) {
	   System.out.print ((char)arg[i]);
	}
	System.out.print ("\n\nLength: " + length + " bytes.\n");
   }
   
      public static int q3query (String msg,byte [] data,String server,Integer port)  {

	DatagramSocket ds;
	DatagramPacket dp;
	InetAddress ia;

//      System.out.print ("Starting Query to server:\n");

      try {
	ds = new DatagramSocket();
      } catch ( java.net.SocketException e) {
        System.out.print ("OK, we caught a java.net.SocketException. :'p\n");
	return -1;
      }
      try {
	ia = InetAddress.getByName(server);
      } catch ( java.net.UnknownHostException e) {
        System.out.print ("OK, we caught a java.net.UnknownHostException. :'p\n");
	return -1;
      }
      String out = "xxxx" + msg;
      byte [] buff = out.getBytes();
      buff[0] = (byte)0xff; // oob
      buff[1] = (byte)0xff;
      buff[2] = (byte)0xff;
      buff[3] = (byte)0xff;
      dp = new DatagramPacket(buff, buff.length, ia, port.intValue());
      try {
	ds.send(dp);
      } catch ( java.io.IOException e) {
        System.out.print ("OK, we caught a java.net.java.io.IOException. :'p\n");
	return -1;
      }

//      buff = new byte[65507];
      dp = new DatagramPacket(data, data.length);
  //    try {
   // 	  ds.setSoTimeout(1000);
	//ds.receive(dp);
   //   } catch ( java.io.IOException e) {
  //      System.out.print ("OK, we caught a java.net.java.io.IOException. :'p\n");
	//return -1;
  //    }
     
//     System.out.print ("Query done.\n");
     return dp.getLength();
    }

      public static void main (String args[])  {
	int i;
        byte [] buff = new byte[65507];
	String rcon="serverinfo";
	String passwd="testing";
	String host="quake";
	Integer port=new Integer(27960);

/* These are the valid messages:
	getstatus
	getinfo
	getchallenge
	connect
	rcon
*/
	for (i=0;i<args.length;i++) {
//	  System.out.print ("arg" + length +": \"" + args[length] + "\" \n");
	  if ((args[i].equals("-rcon")) && (args.length >= i)) {
		rcon=args[i + 1];
		i++;
	  } else
	  if ((args[i].equals("-passwd")) && (args.length >= i)) {
		passwd=args[i + 1];
		i++;
		continue;
	  } else
	  if ((args[i].equals("-host")) && (args.length >= i)) {
		host=args[i + 1];
		i++;
		continue;
	  } else
	  if ((args[i].equals("-port")) && (args.length >= i)) {
		port=Integer.valueOf(args[i + 1]);
		i++;
		continue;
	  } else {
	   System.out.print ("\n\n\tUsage:\n\t\tq3tool [-rcon <remote-command>] ");
	   System.out.print ("[-passwd <server-password>]\n");
	   System.out.print ("\t\t       [-host <remote-host>] [-port <port-number>]\n\n\n");
	   return;
          }
	}

     	System.out.print ("Server Status:\n");
	i=q3query ("getstatus\0",buff,host,port);
	if (i < 0) return;
	dumpchars(buff,i);
     	System.out.print ("Server Info:\n");
	i=q3query ("getinfo\0",buff,host,port);
	if (i < 0) return;
	dumpchars(buff,i);

	i=q3query ("rcon\r" + passwd + "\r" + rcon +"\0",buff,host,port);
	if (i < 0) return;
     	System.out.print ("Hex output:\n");
	dumpvals(buff,i);
     	System.out.print ("\n\nASCII output:\n");
	dumpchars(buff,i);
        return;
      }
}
